package com.zg.autoform.service.impl;

import cn.hutool.core.util.StrUtil;
import com.zg.autoform.dto.DuplicateCheckResult;
import com.zg.autoform.service.DuplicateCheckService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 重复数据检查服务实现
 * @author zg
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class DuplicateCheckServiceImpl implements DuplicateCheckService {

    private final JdbcTemplate jdbcTemplate;

    @Override
    public DuplicateCheckResult checkDuplicate(String tableName, Map<String, Object> data, List<String> checkFields) {
        if (checkFields == null || checkFields.isEmpty()) {
            return DuplicateCheckResult.noDuplicate();
        }

        try {
            // 构建查询条件
            StringBuilder sql = new StringBuilder();
            sql.append("SELECT id");
            for (String field : checkFields) {
                sql.append(", ").append(field);
            }
            sql.append(" FROM ").append(tableName);
            sql.append(" WHERE is_del = 0");

            List<Object> params = new ArrayList<>();
            for (String field : checkFields) {
                Object value = data.get(field);
                if (value != null) {
                    sql.append(" AND ").append(field).append(" = ?");
                    params.add(value);
                } else {
                    sql.append(" AND ").append(field).append(" IS NULL");
                }
            }

            // 添加ROWNUM限制（Oracle兼容）
            sql.append(" AND ROWNUM = 1");

            log.debug("重复检查SQL: {}, 参数: {}", sql.toString(), params);
            List<Map<String, Object>> results = jdbcTemplate.queryForList(sql.toString(), params.toArray());

            if (results.isEmpty()) {
                return DuplicateCheckResult.noDuplicate();
            }

            Map<String, Object> duplicateRecord = results.get(0);
            Long duplicateId = ((Number) duplicateRecord.get("id")).longValue();

            // 提取重复字段值
            Map<String, Object> duplicateFields = new HashMap<>();
            for (String field : checkFields) {
                duplicateFields.put(field, duplicateRecord.get(field));
            }

            String reason = String.format("字段 [%s] 的值 [%s] 已存在",
                String.join(",", checkFields),
                checkFields.stream()
                    .map(field -> String.valueOf(duplicateFields.get(field)))
                    .collect(Collectors.joining(","))
            );

            return DuplicateCheckResult.duplicate(duplicateId, duplicateFields,
                String.join(",", checkFields), reason);

        } catch (Exception e) {
            log.error("检查重复数据失败, 表名: {}, 检查字段: {}", tableName, checkFields, e);
            return DuplicateCheckResult.noDuplicate();
        }
    }

    @Override
    public List<DuplicateCheckResult> batchCheckDuplicate(String tableName, List<Map<String, Object>> dataList, List<String> checkFields) {
        List<DuplicateCheckResult> results = new ArrayList<>();

        if (checkFields == null || checkFields.isEmpty()) {
            for (int i = 0; i < dataList.size(); i++) {
                results.add(DuplicateCheckResult.noDuplicate());
            }
            return results;
        }

        // 为了性能考虑，这里可以优化为批量查询
        // 但为了简单起见，先使用逐条检查
        for (Map<String, Object> data : dataList) {
            results.add(checkDuplicate(tableName, data, checkFields));
        }

        return results;
    }

    @Override
    public void deleteDuplicateData(String tableName, Long duplicateId) {
        try {
            String sql = "UPDATE " + tableName + " SET is_del = 1, update_time = ? WHERE id = ?";
            jdbcTemplate.update(sql, new Date(), duplicateId);
            log.info("删除重复数据成功, 表名: {}, ID: {}", tableName, duplicateId);
        } catch (Exception e) {
            log.error("删除重复数据失败, 表名: {}, ID: {}", tableName, duplicateId, e);
            throw new RuntimeException("删除重复数据失败: " + e.getMessage());
        }
    }

    @Override
    public void updateDuplicateData(String tableName, Long duplicateId, Map<String, Object> newData) {
        try {
            if (newData == null || newData.isEmpty()) {
                log.warn("更新重复数据失败: 新数据为空, 表名: {}, ID: {}", tableName, duplicateId);
                return;
            }

            log.debug("准备更新重复数据, 表名: {}, ID: {}, 原始数据: {}", tableName, duplicateId, newData);

            // 过滤掉系统字段
            Map<String, Object> updateData = newData.entrySet().stream()
                .filter(entry -> !isSystemField(entry.getKey()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

            log.debug("过滤后的更新数据: {}", updateData);

            if (updateData.isEmpty()) {
                log.warn("更新重复数据失败: 过滤后数据为空, 表名: {}, ID: {}", tableName, duplicateId);
                return;
            }

            StringBuilder sql = new StringBuilder();
            sql.append("UPDATE ").append(tableName).append(" SET ");

            List<Object> params = new ArrayList<>();
            List<String> setClauses = new ArrayList<>();

            for (Map.Entry<String, Object> entry : updateData.entrySet()) {
                setClauses.add(entry.getKey() + " = ?");
                params.add(entry.getValue());
            }

            sql.append(String.join(", ", setClauses));
            sql.append(", update_time = ?, ver = ver + 1");
            sql.append(" WHERE id = ?");

            params.add(new Date());
            params.add(duplicateId);

            jdbcTemplate.update(sql.toString(), params.toArray());
            log.info("更新重复数据成功, 表名: {}, ID: {}", tableName, duplicateId);

        } catch (Exception e) {
            log.error("更新重复数据失败, 表名: {}, ID: {}", tableName, duplicateId, e);
            throw new RuntimeException("更新重复数据失败: " + e.getMessage());
        }
    }

    /**
     * 判断是否为系统字段
     */
    private boolean isSystemField(String fieldName) {
        if (fieldName == null) {
            return false;
        }
        String lowerFieldName = fieldName.toLowerCase();
        boolean isSystem = Arrays.asList("id", "create_time", "create_by", "update_time", "update_by", "ver", "is_del")
            .contains(lowerFieldName);
        log.debug("字段 {} 是否为系统字段: {}", fieldName, isSystem);
        return isSystem;
    }
}
